1. Field of the Invention
This invention relates to computer systems, and more particularly to dynamic class reloading and versioning.
2. Description of Related Art
Java™ may be described as a class-based, platform-independent programming language. A virtual machine may be generally described as a software implementation of a central processing unit (CPU) that runs compiled code (e.g., applets and applications) on a given system or machine, where the code itself remains the same from one system or machine to another. In Java™ technology, the virtual machine that runs compiled Java™ code is referred to as a Java Virtual Machine (JVM™). In the JVM, the basic unit of software is the (Java™) class. A class-based software application (e.g., a Java™ application or applet) running in a virtual machine (e.g., a JVM) might consist of tens, hundreds, or thousands of classes. A class is generally composed of fields that hold data or references to other objects, and methods. The body of each method contains executable instructions (bytecode) that implements a part of the program logic. In order to use a class—to access the data it stores or to execute its methods—the virtual machine (e.g., JVM) first loads the class into memory.
Java™, J2EE™, Java™ EE, and JVM™, as used throughout this document, are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.
Class Loaders
Class loaders are one of the cornerstones of virtual machine architectures such as the Java™ Virtual Machine (JVM™) architecture. A class loader is an object that is responsible for loading classes. Programmatically speaking, class loaders are objects that may be defined in code (e.g. Java™ code). In Java™ technology, class loaders are instances of subclasses of abstract class ClassLoader. Given the name of a class, a class loader may attempt to locate or generate data that constitutes a definition for the class. A typical strategy is to transform the name into a file name and then read a “class file” of that name from a file system. The default class loading behavior in the JVM is to load the class file from a specified location (e.g., specified in a class path) into the memory and to execute the bytecode as and when the request comes in for the particular class. Whenever a class refers to another class, for example, by initializing a field or local variable, the referent is immediately loaded (or delegated by that class loader to its parent class loader) by the same class loader that loaded the referencing class. Class loaders may enable a system (e.g., a virtual machine) to load classes without knowing anything about the underlying file system semantics, and may allow applications to dynamically load classes such as Java™ classes as extension modules
Java™ and Java™ Virtual Machine (JVM™) Technology
In Java™ technology, a class loader loads the bytecode from a class's class file into the Java™ Virtual Machine (JVM™, also referred to herein as simply VM), making it available for use in an application. A given class loader can load only one class of a given name. Conventionally, once a class loader has loaded a class, there is no way for application code or the class loader itself to unload the class. Different class loaders may load the same or different bytecode using the same class name. The VM's type system considers such classes to be different; each class is implicitly qualified by the class loader that loads it.
The JVM provides features via which Java™ code, e.g. a programmer's custom Java™ code, can gain control as a class is being loaded and transform the bytecode that will be used in defining the class. For example, classes in the java.instrumentation package in Java™ may be leveraged to provide this feature.
Once a class has been defined, conventional JVM technology allows Java™ code to redefine the class in restricted ways, as described in the Java™ documentation for the java.instrumentation package. Conventionally, the only change allowed is to rewrite the bytecode inside method bodies. The redefinition allowed by conventional JVM technology cannot change the so-called shape of the class by adding or removing fields or methods or changing the signatures of methods or the types of fields.
Java™ technology includes the abstract class java.lang.ClassLoader, also referred to herein as ClassLoader or class loader. Any Java™ code that retrieves bytecode for use in defining classes must extend ClassLoader. Many of its methods can be overridden by subclasses that extend ClassLoader, and in fact some of ClassLoader's methods are defined as abstract, meaning that they must be overridden by subclass implementations. On the other hand, ClassLoader declares some of its methods as final, meaning subclasses cannot override them. The implementations of such final methods in ClassLoader are guaranteed to be the ones that execute. An important method is defineClass. The several variants of this method (all final) contain the logic that actually converts a byte array (or a byte buffer) containing the bytecode of a class into a class definition that can be used throughout the JVM.
Further, the JVM associates a defined class with the specific class loader that invokes defineClass (also referred to herein as the define class method) for that class. This is essentially how the VM implicitly qualifies each class with the loader that loaded the class.
A software developer writing an application, for example an application in a Java™ Platform, Enterprise Edition (which may be referred to as Java™ EE or J2EE™) environment application server, typically follows a cycle of work that involves editing his or her source code, recompiling it, deploying or redeploying the application into the application server, and testing the revisions by running the application, repeating this cycle many times to fix problems in the application or to enhance the application. Often, the application server must do considerable work to redeploy an application, and even when this step takes only a relatively short time, it can still be disruptive to the flow of the developer's work.
Conventionally, VM technology provides limited support for changing a class once it has been loaded. For example, the Java™ HotSpot™ VM supports replacing the bytecode instructions in the bodies of methods, but does not support adding or removing fields or methods, or changing the signature of any method. Such changes are common in normal software development. Conventionally, to make such changes and then use them, a developer must either redeploy the application (if he or she is using a container-based product such as an application server) or restart the VM and rerun the program. Redeploying or rerunning the application is potentially time-consuming and expensive, in part because all classes—even those that have not changed—must be reloaded as part of the redeployment or restart. In addition, redeploying or restarting causes the loss of the current program state. Redeploying or restarting takes significant time and interrupts the flow of the developer's work as he or she performs repetitive cycles of the edit, build, deploy, and run development process.